package com.lyf.network.learn.nio.buffer;

import org.junit.Test;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

/**
 *
 * @AUTHOR LYF
 * @DATE 2022/6/10
 * @VERSION 1.0
 * @DESC
 * 关于读写的方向问题
 *
 * 1.对于Buffer
 * （1）Buffer的写入：
 * -- channel.read(buffer) : channel → buffer相对于channel是输出;read into buffer
 * -- buffer.put(..)
 * （2）Buffer的读出
 * -- channel.write(buffer) :从 buffer → channel
 * -- buffer.get()
 * 2.对于IO
 *
 * InputStream:读入，，inputStream.read(buffer) 外部 → 内存（内部）
 * OutputStream:写出，，outputStream.write(buffer) 内存 → 写出到外部
 *
 * stream和channel都是一个通道，连接点，并非断点，不存储数据，，一般代表外部？？
 * read：流OR通道 → 读取到内存处理的buffer中来
 * write：buffer → 流OR通道
 * buffer只是存储的参数，参考物始终是程序本身；read 则是读进程序；write则是写出程序；stream or channel只是连接承载
 *
 * 3.关于读写
 *
 * 操作的基本两种方式，CRUD-归根阶段也是读写；
 * 在对数据库操作的事务控制，并发问题主要也是写写的问题--
 *
 *
 */
public class ReadWriteDirection {
    private String path = "E:\\JavaProjects\\LearnProjects\\learn-practice\\java-base\\src\\main\\java\\com\\lyf\\network\\learn\\nio\\files\\tmp3.txt";

    /**
     * 测试IO、Buffer的write、read方向问题
     */
    @Test
    public void test() throws Exception{

        FileInputStream fileIn = new FileInputStream(path);
        // 注：不能提前创建fileOut对象，会导致数据为空--
        //FileOutputStream fileOut = new FileOutputStream(path);

        // 测试Stream
        // 暂存区--缓冲区
        byte [] buffer = new byte[1024];
        // 测试读入
        int reads;
        while((reads=fileIn.read(buffer))!=-1){
            System.out.println(reads);
            System.out.println(new String(buffer,0,reads));
        }


        // 测试写出
        FileOutputStream fileOut = new FileOutputStream(path);

        // 会直接覆盖--？？
        fileOut.write("out".getBytes());

        // 测试Buffer、Channel
        FileChannel fileChannel1 = fileIn.getChannel();
        FileChannel fileChannel2 = fileOut.getChannel();
        System.out.println(fileChannel1==fileChannel2);

        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

        // 读入--
        System.out.println("采用channel 读取数据:");

        /*
         *@link{java.nio.channels.NonReadableChannelException}
         */
//        while ( fileChannel2.read(byteBuffer) !=-1){// read(dst) src -- read  buffer为目的地 是接收数据的
//            byteBuffer.flip();//切换模式，切换到buffer 的 读取数据 , 调整position,, -- 理解 position,limit,capacity三个属性
//            System.out.println((char) byteBuffer.get());
//        }
        fileIn.close();
        fileOut.close();

        FileInputStream fileIn2 = new FileInputStream(path);
        FileChannel fileChannel = fileIn2.getChannel();
        while (fileChannel.read(byteBuffer)!=-1){// 此处的判断依据则是position的位置？
            byteBuffer.flip();// 切换(position指向0，读到Limit处，非null值） 读取buffer模式，此时buffer又代表外部了
            while(byteBuffer.hasRemaining()){
                System.out.println((char) byteBuffer.get());
            }
            byteBuffer.clear();// 清空buffer,为什么不清空则读出的数据始终非空？
        }

        // 测试写 java.nio.channels.NonWritableChannelException
//        ByteBuffer writeBuffer = ByteBuffer.allocate(1024);
//        writeBuffer.put("hello".getBytes());
//        fileChannel.write(writeBuffer);

        fileChannel.close();
        fileIn2.close();

        fileOut = new FileOutputStream(path);
        FileChannel fileChannel3 = fileOut.getChannel();
        fileChannel3.write(ByteBuffer.wrap("hello".getBytes()));
        fileChannel3.close();
        fileOut.close();
    }
}
